home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-04
/
bipl.zip
/
PROGS.ZIP
/
IIENCODE.ICN
< prev
next >
Wrap
Text File
|
1993-01-27
|
6KB
|
207 lines
############################################################################
#
# File: iiencode.icn
#
# Subject: Program to encode text in the style of uuencode
#
# Author: Richard L. Goerwitz
#
# Date: June 3, 1991
#
###########################################################################
#
# Version: 1.8
#
###########################################################################
#
# This is an Icon port of the UNIX/C uuencode utility. Since
# uuencode is publicly distributable BSD code, I simply grabbed a
# copy, and rewrote it in Icon. The only basic functional changes I
# made to the program were: 1) To simplify the notion of file mode
# (everything is encoded with 0644 permissions), and 2) to add sup-
# port for xxencode format (which will generally pass unscathed even
# through EBCDIC sites).
#
# Iiencode's usage is compatible with that of the UNIX uuencode
# command, i.e. a first (optional) argument gives the name the file
# to be encoded. If this is omitted, iiencode just uses the standard
# input. The second argument specifies the name the encoded file
# should be given when it is ultimately decoded.
#
# Extensions to the base uuencode command options include -x and -o.
# An -x tells iiencode to use xxencode (rather than uuencode) format.
# Option -o causes the following argument to be used as the file
# iiencode is to write its output to (the default is &output). Note
# that, on systems with newline translation (e.g. MS-DOS), the -o
# argument should always be used.
#
# iiencode [infile] [-x] remote-filename [-o] output-filename
#
# BUGS: Slow. I decided to go for clarity and symmetry, rather than
# speed, and so opted to do things like use ishift(i,j) instead of
# straight multiplication (which under Icon v8 is much faster). Note
# that I followed the format of the newest BSD release, which refuses
# to output spaces. If you want to change things back around so that
# spaces are output, look for the string "BSD" in my comments, and
# then (un)comment the appropriate sections of code.
#
############################################################################
#
# See also: iidecode.icn
#
############################################################################
procedure main(a)
local ofs, in_filename, out_filename, in, out, is_xx, remotename, usage
usage := "usage: iiencode [infile] [-x] _
remote-filename [-o output-filename]"
# Parse arguments.
ofs := 0
while (ofs +:= 1) <= *a do {
case a[ofs] of {
"-x" : is_xx := 1
"-o" : out_filename := a[ofs +:= 1] | stop(usage)
default : {
if not (/in_filename := a[ofs]) then
remotename := a[ofs]
}
}
}
# If remotename is null, set it to in_filename. If it's still
# null, then abort with usage message.
if /(/remotename :=: in_filename) then {
write(&errout,usage)
exit(2)
}
# If no input filename was supplied, use &input.
if /in_filename then
/in := &input
else
in := open(in_filename) |
stop(&errout,"Can't open input file, ",in_filename,".\n",usage)
# If an output filename was specified, open it for writing.
if \out_filename then
out := open(out_filename, "wu") |
stop("Can't open output file, ",out_filename,".\n",usage)
# Set null out to &output; advise DOS users to use -o option.
else {
out := &output
if find("MS-DOS",&features) then
write(&errout, "Okay, but the -o option is recommended for DOS.")
}
# This generic version of uuencode treats file modes in a primitive
# manner so as to be usable in a number of environments. Please
# don't get fancy and change this unless you plan on keeping your
# modified version on-site (or else modifying the code in such a
# way as to avoid dependence on a specific operating system).
writes(out, "begin 644 ",remotename,"\n")
encode(out, in, is_xx)
writes(out, "end\n")
every close(in|out)
exit(0)
end
procedure encode(out, in, is_xx)
# Copy from in to standard output, encoding as you go along.
local line
if \is_xx then
ENC := xxENC
# 1 (up to) 45 character segment
while line := reads(in, 45) do {
writes(out, ENC(*line))
line ? {
while outdec(move(3), out)
pos(0) | outdec(left(tab(0), 3, " "), out)
}
writes(out, "\n")
}
# Uuencode adds a space and newline here, which is decoded later
# as a zero-length line (signals the end of the decoded text).
# writes(" \n")
# The new BSD code (compatible with the old) avoids outputting
# spaces by writing a ` (see also how it handles ENC() below).
if \is_xx
then writes(out, "+\n")
else writes(out, "`\n")
end
procedure outdec(s, out)
# Output one group of 3 bytes (s) to standard output. This is one
# case where C is actually more elegant than Icon. Note well!
local c1, c2, c3, c4
c1 := ishift(ord(s[1]),-2)
c2 := ior(iand(ishift(ord(s[1]),+4), 8r060),
iand(ishift(ord(s[2]),-4), 8r017))
c3 := ior(iand(ishift(ord(s[2]),+2), 8r074),
iand(ishift(ord(s[3]),-6), 8r003))
c4 := iand(ord(s[3]),8r077)
every writes(out, ENC(c1 | c2 | c3 | c4))
return
end
procedure ENC(c)
# ENC is the basic 1 character encoding procedure to make a char
# printing.
# New BSD code doesn't output spaces...
return " " ~== char(iand(c, 8r077) + 32) | "`"
# ...the way the old code does:
# return char(iand(c, 8r077) + 32)
end
procedure xxENC(c)
# ENC is the basic 1 character encoding procedure to make a char
# printing.
local k, ordval, oversizes
static ordtbl
initial {
ordval := -1
ordtbl := table()
every k := !"+-0123456789ABCDEFGHIJKLMNOPQRST_
UVWXYZabcdefghijklmnopqrstuvwxyz"
do insert(ordtbl, ordval +:= 1, k)
oversizes := 0
}
# Table lookup isn't the fastest ever, I know. If I thought about
# it a bit longer, I'm sure I could do this using map. This would
# require some type conversions, but I wonder whether it would still
# be substantially faster. If anyone tries this out and times the
# results, please communicate to me the results!
return ordtbl[iand(c, 8r077)]
end